package kit.docker.interceptor;

import com.docker.core.constant.ConfigConstant;
import com.docker.core.constant.MainConstant;
import com.docker.core.mvc.Remark;
import com.docker.login.LoginRedis;
import com.docker.sys.app.AppBean;
import com.docker.sys.app.AppRedis;
import com.jfinal.kit.PropKit;
import com.jfinal.kit.StrKit;
import kit.docker.datetime.DateKit;
import kit.docker.exception.BaseException;
import kit.docker.redis.RedisConstant;
import kit.docker.redis.RedisKit;
import kit.docker.security.MD5Kit;
import kit.docker.web.APIResCode;
import kit.docker.web.RequestKit;

import javax.servlet.http.HttpServletRequest;

/**
 * @Author ldl
 * @Create 2020/10/21 021 12:08
 */
@Remark("拦截器校验方法")
public class InterceptorKit {

    //校验参数完整性
    public static void checkField(String... fields) {
        for (String field : fields) {
            if (StrKit.isBlank(field)) {
                throw new BaseException(APIResCode.API_SECURITY_PROTOCOL_AUTHENTICATION_FAILED, "缺少必要数据");
            }
        }
    }

    public static void checkPublic(HttpServletRequest request, String appId, String timestamp, String sign, String token, boolean useToken) {
        //校验时间戳
        checkTimestap(timestamp);

        AppBean app = AppRedis.getApp(appId);

        //校验授权平台
        if ("1".equals(app.getRestrict_access())) {
            checkPlatform(app.getRestrict_platform(), request);
        }
        //校验应用授权时间
        checkAppExpireTime(app.getExpire_time());

        //校验签名
        checkSign(request, sign, app.getAdd_secret(), app.getApp_secret());

        if (useToken) {
            //校验用户身份token
            checkUserToken(app, token);
        }
    }

    //校验用户身份token
    private static void checkUserToken(AppBean app, String token) {
        if (StrKit.isBlank(token)) {
            throw new BaseException(APIResCode.SESSION_TIME_OUT);
        }
        String key = RedisConstant.USER_SESSION_TOKEN + app.getApp_id() + ":" + token;
        if (!RedisKit.exists(MainConstant.REDIS_DOCKER, key)) {
            throw new BaseException(APIResCode.SESSION_TIME_OUT);
        }
        LoginRedis.rollUserLoginSession(app, token);
    }

    //校验签名
    private static void checkSign(HttpServletRequest request, String sign, String addSecret, String appSecret) {
        String paramStr = RequestKit.formatParamMapToString(RequestKit.getParamMap(request, "sign", "file"));
        if ("1".equals(addSecret)) {
            paramStr = paramStr + appSecret;
        }
        if (!sign.equals(MD5Kit.encodeMD5Hex(paramStr))) {
            throw new BaseException(APIResCode.API_SECURITY_PROTOCOL_AUTHENTICATION_FAILED, "数据校验失败");
        }
    }

    //校验应用授权时间
    private static void checkAppExpireTime(String expireTime) {
        if (StrKit.notBlank(expireTime)) {
            if (DateKit.compare(DateKit.getNowDateTime(), expireTime) >= 0) {
                throw new BaseException(APIResCode.API_SECURITY_PROTOCOL_AUTHENTICATION_FAILED, "应用授权失败");
            }
        }
    }

    //校验是否授权平台
    private static void checkPlatform(String restrictPlatform, HttpServletRequest request) {
        if (restrictPlatform.contains("wx")) {
            String userAgent = request.getHeader("user-agent").toLowerCase();
            if (StrKit.isBlank(userAgent) || !userAgent.toLowerCase().contains("micromessenger")) {
                throw new BaseException(APIResCode.API_SECURITY_PROTOCOL_AUTHENTICATION_FAILED, "仅限微信内访问");
            }
        } else {
            throw new BaseException(APIResCode.API_SECURITY_PROTOCOL_AUTHENTICATION_FAILED, "未授权平台");
        }
    }

    //校验时间戳
    private static void checkTimestap(String timestamp) {
        long reqTimestamp = Long.parseLong(timestamp);
        long nowTimestamp = DateKit.getNowTimestamp();
        int defferTime = PropKit.getInt(ConfigConstant.HTTP_DEFFER_TIME, 120);
        if (reqTimestamp + defferTime < nowTimestamp) {
            throw new BaseException(APIResCode.API_SECURITY_PROTOCOL_AUTHENTICATION_FAILED, "时间校验失败");
        }
    }

}
